/*
 *    Copyright (c) 2018-2025, cloud All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: cloud
 */
package com.fuyao.cloud.space.position.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fuyao.cloud.common.core.util.R;
import com.fuyao.cloud.common.data.datascope.DataScope;
import com.fuyao.cloud.common.data.resolver.NumberResolver;
import com.fuyao.cloud.space.constant.*;
import com.fuyao.cloud.space.entity.RoomHouse;
import com.fuyao.cloud.space.entity.RoomPosition;
import com.fuyao.cloud.space.house.service.RoomHouseService;
import com.fuyao.cloud.space.position.mapper.RoomPositionMapper;
import com.fuyao.cloud.space.position.service.RoomPositionService;


import com.fuyao.cloud.space.vo.RoomPositionExportVO;
import com.fuyao.cloud.space.vo.PositionVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 位置管理
 *
 * @author 时间的朋友
 * @date 2021-11-16 19:23:41
 */
@Service
@AllArgsConstructor
public class RoomPositionServiceImpl extends ServiceImpl<RoomPositionMapper, RoomPosition> implements RoomPositionService {
	private final RoomHouseService fyRoomHouseService;

	@Override
	public boolean save(RoomPosition entity) {
		beforeSaveAndUpdate(entity);
		return super.save(entity);
	}

	@Override
	public boolean updateById(RoomPosition entity) {
		beforeSaveAndUpdate(entity);
		return super.updateById(entity);
	}


	private void beforeSaveAndUpdate(RoomPosition entity) {
		if (StrUtil.isEmpty(entity.getCode())){
			entity.setCode(NumberResolver.getNumberStr(PositionConstant.DEFAULT_TYPE, PositionConstant.POSITION_CODE).getData());
		}
		// 获取房间名称
		if (entity.getHouseId() != null) {
			RoomHouse house = this.fyRoomHouseService.getById(entity.getHouseId());
			entity.setHouseName(house.getName());
			entity.setDataCode(house.getDataCode() + "." + entity.getCode());
			// parentName = 区域.楼栋.楼层 取房屋信息
			entity.setParentId(house.getId());
			entity.setParentName(house.getParentFullname());
			// 排序号为零时 自动设置排序好
			if (entity.getOrdernumber() == null || entity.getOrdernumber() == 0) {
				Long orderNum = NumberResolver.getNumberValue(PositionConstant.DEFAULT_TYPE, house.getCode()).getData();
				entity.setOrdernumber(orderNum);
			}
		} else {
			entity.setDataCode(entity.getCode());
		}
	}

	@Override
	public List<RoomPositionExportVO> listExcel(RoomPosition fyRoomPosition) {
		return this.baseMapper.listExcel(fyRoomPosition);
	}

	@Override
	public List<Tree<Long>> selectTree(QueryWrapper<RoomPosition> queryWrapper) {
		// 查询位置信息
		List<RoomPosition> positionList = this.baseMapper.selectList(queryWrapper);
		// 查询数据权限内房屋信息
		List<Long> positionOwnIdList = this.baseMapper.selectListByScope(queryWrapper, new DataScope()).stream()
				.map(RoomPosition::getDeptId).collect(Collectors.toList());
		List<RoomHouse> houseList = this.fyRoomHouseService.list();
		// 权限内房屋信息
		List<TreeNode<Long>> collect = positionList.stream()
				.sorted(Comparator.comparing(RoomPosition::getOrdernumber)).map(position -> {
					TreeNode<Long> treeNode = new TreeNode();
					treeNode.setId(position.getId());
					treeNode.setParentId(0L);
					treeNode.setName(position.getName());
					treeNode.setWeight(position.getOrdernumber());
					// 有权限不返回标识
					Map<String, Object> extra = new HashMap<>(8);
					extra.put("isLock", !positionOwnIdList.contains(position.getDeptId()));
					extra.put("createTime", position.getCreateTime());
					Optional<RoomHouse> houseOptional = houseList.stream().filter(house -> house.getId().equals(position.getHouseId())).findFirst();
					if(houseOptional.isPresent()){
						RoomHouse house = houseOptional.get();
						extra.put("houseId", house.getId());
						extra.put("fullName", house.getParentFullname()+"."+position.getName());
					}
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList());
		return TreeUtil.build(collect, 0L);
	}

	@Override
	public List<TreeNode<String>> getTreeNode() {
		// 查询房屋信息
		List<RoomPosition> positionList = this.baseMapper.selectList(Wrappers.emptyWrapper());
		// 查询数据权限内房屋信息
		List<Long> positionOwnIdList = this.baseMapper.selectListByScope(Wrappers.emptyWrapper(), new DataScope()).stream()
				.map(RoomPosition::getDeptId).collect(Collectors.toList());

		// 权限内房屋信息
		List<TreeNode<String>> collect = this.fyRoomHouseService.getTreeNode(Wrappers.<RoomHouse>query().lambda().ne(RoomHouse::getTypeCode, "CK"));
		collect.addAll(positionList.stream()
				.sorted(Comparator.comparing(RoomPosition::getOrdernumber)).map(position -> {
					TreeNode<String> treeNode = new TreeNode();
					treeNode.setId(PositionConstant.POSITION_TREE_NAME+"."+position.getId());
					treeNode.setParentId(HouseConstant.HOUSE_TREE_NAME+"."+position.getHouseId());
					treeNode.setName(position.getName());
					treeNode.setWeight(position.getOrdernumber());
					// 有权限不返回标识
					Map<String, Object> extra = new HashMap<>(8);
					extra.put("isLock", !positionOwnIdList.contains(position.getDeptId()));
					extra.put("createTime", position.getCreateTime());
					extra.put("affiliName",PositionConstant.POSITION_TREE_NAME);
					extra.put("affiliParentName",HouseConstant.HOUSE_TREE_NAME);
					extra.put("idCard", position.getId());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList()));
		return collect;
	}

	@Override
	public Page<RoomPosition> getTreePage(Page page, Long id, String affiliName) {
		List<Long> ids=getTreeParam(id,affiliName);
		ids.add(0L); // 如果为空会报错
		return this.baseMapper.selectPage(page,Wrappers.<RoomPosition>lambdaQuery().in(RoomPosition::getId,ids));
	}

	/**
	 * 获取树形参数
	 * @param id
	 * @param affiliName
	 * @return
	 */
	@Override
	public List<Long> getTreeParam(Long id, String affiliName) {
		List<Long> ids;
		if (affiliName.equals(HouseConstant.HOUSE_TREE_NAME)){
			ids=this.baseMapper.getIdByParentId(new Long[]{id});
		}else {
			List<Long> parentIds= this.fyRoomHouseService.getTreeParam(id,affiliName);
			if (parentIds.size() ==0){
				return new ArrayList<>();
			}
			ids=this.baseMapper.getIdByParentId(parentIds.toArray(new Long[parentIds.size()]));
		}
		return Optional.ofNullable(ids).orElse(new ArrayList<>());
	}

	@Override
	public List<Tree<String>> lazyTree(String houseId) {
		String[] ids=houseId.split("-");
		if (ids.length==2){
			if (!ids[0].equals(HouseConstant.HOUSE_TREE_NAME)){
				return new ArrayList<>();
			}
		}
		return this.lazyTree(ids[1]);
	}

	@Override
	public List<Tree<String>> lazyTree(Long houseId) {
		// lambda 查询条件
		LambdaQueryWrapper<RoomPosition> wrappers=Wrappers.<RoomPosition>lambdaQuery().eq(RoomPosition::getHouseId,houseId);
		// 查询房屋信息
		List<RoomPosition> positionList = this.baseMapper.selectList(wrappers);
		// 查询数据权限内房屋信息
		List<Long> positionOwnIdList = this.baseMapper.selectListByScope(wrappers, new DataScope()).stream()
				.map(RoomPosition::getDeptId).collect(Collectors.toList());

		// 权限内房屋信息
		List<TreeNode<String>> collect = this.fyRoomHouseService.getTreeNode(Wrappers.<RoomHouse>query().lambda().ne(RoomHouse::getTypeCode, "CK"));
		collect.addAll(positionList.stream()
				.sorted(Comparator.comparing(RoomPosition::getOrdernumber)).map(position -> {
					TreeNode<String> treeNode = new TreeNode();
					treeNode.setId(PositionConstant.POSITION_TREE_NAME+"."+position.getId());
					if (position.getParentId() != 0){
						treeNode.setParentId(PositionConstant.POSITION_TREE_NAME+"."+position.getParentId());
					}else {
						treeNode.setParentId(HouseConstant.HOUSE_TREE_NAME+"."+position.getHouseId());
					}
					treeNode.setName(position.getName());
					treeNode.setWeight(position.getOrdernumber());
					// 有权限不返回标识
					Map<String, Object> extra = new HashMap<>(8);
					extra.put("isLock", !positionOwnIdList.contains(position.getDeptId()));
					extra.put("createTime", position.getCreateTime());
					extra.put("affiliName",PositionConstant.POSITION_TREE_NAME);
					extra.put("affiliParentName",HouseConstant.HOUSE_TREE_NAME);
					extra.put("idCard", position.getId());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList()));
		return TreeUtil.build(collect, HouseConstant.HOUSE_TREE_NAME+ "."+houseId);
	}

	@Override
	public R judgeChilden() {
		return null;
	}

	@Override
	public PositionVO getPositionById(Long id) {
		Objects.requireNonNull(id);
		RoomPosition fyRoomPosition = this.getById(id);
		RoomHouse house = this.fyRoomHouseService.getById(fyRoomPosition.getHouseId());
		PositionVO positionVO = new PositionVO();
		BeanUtil.copyProperties(fyRoomPosition, positionVO);
		positionVO.setTypeCode(house.getTypeCode());
		positionVO.setTypeName(house.getTypeName());
		return positionVO;
	}

	@Override
	public List<PositionVO> listPositionVO() {
		List<RoomHouse> houseList = this.fyRoomHouseService.list();
		List<RoomPosition> positionList = this.list();
		return positionList.stream().map(position -> {
			PositionVO positionVO = new PositionVO();
			BeanUtil.copyProperties(position, positionVO);
			RoomHouse fyRoomHouse = houseList.stream().filter(house -> house.getId().equals(position.getHouseId())).findFirst().orElse(new RoomHouse());
			positionVO.setTypeCode(fyRoomHouse.getTypeCode());
			positionVO.setTypeName(fyRoomHouse.getTypeName());
			return positionVO;
		}).collect(Collectors.toList());
	}


}
